﻿#ifndef LIVEWATCH_H
#define LIVEWATCH_H

#include <QWidget>
#include <QAbstractItemModel>
#include <QTableView>
#include <QItemDelegate>
#include <QVector>
/*******************************************************************
* 类名: WatchView
* 描述: 查看变量（视图）。视图主要用于显示模型中的数据项，因此它的实现也是比较简单的，
* 只需要负责一些界面的整体布局、渲染工作
*******************************************************************/
class WatchView : public QTableView
{
    Q_OBJECT
public:
    //构造函数
    explicit WatchView(QWidget *parent = nullptr):QTableView(parent)
    {
        setEditTriggers(QAbstractItemView::CurrentChanged | //改变或双击触发编辑器
                        QAbstractItemView::DoubleClicked);
        //简单的界面设计
        setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); //根据需要显示滚动条
        setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
        setGridStyle(Qt::DashLine);                          //表格内的网格样式
    }
    //析构函数
    ~WatchView(){}
};
/*******************************************************************
* 类名: WatchDelegate
* 描述: 查看变量（委托）。委托为模型中的数据提供一些特殊的显示效果，同时负责提供编辑器。
*  Qt 建议使用 QStyledItemDelegate 来实现自定义委托。
*******************************************************************/
class WatchDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    explicit WatchDelegate(QObject *parent = 0);
    ~WatchDelegate();
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
    void setEditorData(QWidget *editor, const QModelIndex &index ) const override;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const override;
    void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
    void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index )override;
    void setTailIndex(const QModelIndex &index);             //设置尾行模型索引
signals:
    void clickToAdd(QString addr) const;                     //编辑最后一行，触发

private:
    //表格尾行（clickToAdd）的索引，因为要长时间使用所以使用 QPersistentModelIndex
    QPersistentModelIndex *tailIndex;
};

/*******************************************************************
* 类名: WatchModel
* 描述: 查看变量（模型）。模型类用于直接管理数据，如数据的插入、删除、更改等。
* 模型中比较难理解的是模型索引和项角色，它们究竟做了什么？模型项应该是怎样结构呢？
* 为什么不同的项角色能让模型项呈现不同的值。
*******************************************************************/
class WatchModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    enum layout{          //参数监控界面布局（标签位置）
        columns = 3,      //总列数
        varPos = 0,       //变量名列位置
        valuePos = 1,     //变量值列位置
        formatPos = 2,    //变量值格式列位置
    };

    explicit WatchModel(QObject *parent = Q_NULLPTR);    //构造函数
    ~WatchModel();                                       //析构函数

    //获取表头信息
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
    //设置表头
    bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
    // 构造父节点下子节点的索引
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
    // 通过子节点索引获取父节点索引
    QModelIndex parent(const QModelIndex &child) const override;
    // 获取父节点下子节点的行数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    // 获取父节点下子节点列数
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    // 获取节点数据
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    //设置模型项数据
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    //返回index的模型项标志（如可编辑等）
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    //插入count行数据
    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
    //删除 count 行数据
    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
    //获取最后一行<click to add>的索引
    QModelIndex getTailIndex(void) const;

public slots:
    void appendRow(QString name);      //追加一行

protected:
    QString editToDisplay(int row, int column) const;   //将 Qt::EditRole 类型转为 Qt::DisplayRole
    quint16 displayToEdit(QString display, int row = 0, int column = 0) const;//将 Qt::DisplayRole 类型转为 Qt::EditRole

private:
    //需要监控的参数表(最后一行保留出来用于添加行)，该表是按照Qt::EditRole类型存放的。
    QVector<QVector<quint16> > *tab;
    QStringList VHeader;                //列标题

};
#endif // LIVEWATCH_H
/**********************************END OF FILE**********************************/
